package org.bjf.modules.user.service;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.bjf.modules.user.bean.User;
import org.bjf.utils.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * redis 排行榜
 *
 * @author bjf
 * @date 2017/11/27
 */
@Service
@Slf4j
public class RankService {

  @Resource
  private RedisUtil redis;
  @Resource
  private UserService userService;

  /**
   * 新增榜单分数
   *
   * @param rankKey 排行榜key
   * @param userId 用户ID
   * @param score 分数
   */
  public void addScore(String rankKey, Long userId, double score) {
    // 与榜单旧分数对比，高于才更新
    Double oldScore = redis.zScore(rankKey, userId);
    if (oldScore == null || oldScore < score) {
      redis.zAdd(rankKey, userId, score);
    }
  }

  /**
   * 查询用户排名
   * @param rankKey 排行榜key
   * @param userId 用户ID
   */
  public RankInfo getUserRank(String rankKey, long userId) {
    //===1.查询用户自己排名
    User user = userService.get(userId);
    RankInfo rankInfo = new RankInfo();
    BeanUtils.copyProperties(user, rankInfo);
    Double score = redis.zScore(rankKey, userId);
    if (score == null) {
      rankInfo.setScore(0D);
      //-1表示无排名
      rankInfo.setRanking(-1L);
    } else {
      Long ranking = redis.zReverseRank(rankKey, userId);
      rankInfo.setRanking(ranking + 1);
      rankInfo.setScore(score);
    }

    return rankInfo;
  }


    /**
     * 榜单列表
     * @param rankKey 排行榜key
     */
  public List<RankInfo> listRankPage(String rankKey, long page, long pageSize) {

    //===1.分页查出redis榜单
    Set<TypedTuple> tuples = redis
        .zReverseRangeWithScores(rankKey, (page - 1) * pageSize, page * pageSize);

    //===2.查询用户信息
    List<Long> uIds = tuples.stream()
        .map(e -> Long.valueOf(Objects.requireNonNull(e.getValue()).toString()))
        .collect(Collectors.toList());
    Map<Long, User> userMap = userService.mapByIds(uIds, Long.class);

    //===3.返回rankList
    List<RankInfo> rankUsers = new ArrayList<>(tuples.size());
    for (TypedTuple tuple : tuples) {
      User user = userMap.get(Long.valueOf(tuple.getValue().toString()));
      if (user == null) {
        continue;
      }
        RankInfo rank = new RankInfo();
      BeanUtils.copyProperties(user, rank);
      rank.setScore(tuple.getScore());
      rank.setRanking(redis.zReverseRank(rankKey, tuple.getValue()) + 1L);
      rankUsers.add(rank);
    }
    return rankUsers;
  }


  @Data
  public static class RankInfo {

    private Long userId;
    /**
     * 分数
     */
    private Double score;
    /**
     * 排名
     */
    private Long ranking;
    /**
     * 昵称
     */
    private String nickName;
    /**
     * 用户头像
     */

    private String headImg;
  }


}
